const dgram = require('dgram')
const dns = require('dns');
/* const { syncBuiltinESMExports } = require('module');
const { threadId } = require('worker_threads'); */
const server = dgram.createSocket('udp4')

function parseHost(msg) {
    let num = msg.readUInt8(0);
    let offset = 1;
    let host = "";
    while (num !== 0) {
        host += msg.subarray(offset, offset + num).toString();
        offset += num;

        num = msg.readUInt8(offset);
        offset += 1;

        if (num !== 0) {
            host += '.'
        }
    }
    return host
}

function copyBuffer(src, offset, dst) {
    for (let i = 0; i < src.length; ++i) {
        dst.writeUInt8(src.readUInt8(i), offset + i)
    }
}

function resolve(msg, rinfo) {
    const queryInfo = msg.subarray(12)
    const response = Buffer.alloc(28 + queryInfo.length)
    let offset = 0

    // Transaction ID
    const id = msg.subarray(0, 2)
    copyBuffer(id, 0, response)
    offset += id.length

    // Flags
    response.writeUInt16BE(0x8180, offset)
    offset += 2

    // Questions
    response.writeUInt16BE(1, offset)
    offset += 2

    // Answer RRs
    response.writeUInt16BE(1, offset)
    offset += 2

    // Authority RRs & Additional RRs
    response.writeUInt32BE(0, offset)
    offset += 4
    copyBuffer(queryInfo, offset, response)
    offset += queryInfo.length

    // offset to domain name
    response.writeUInt16BE(0xC00C, offset)
    offset += 2
    const typeAndClass = msg.subarray(msg.length - 4)
    copyBuffer(typeAndClass, offset, response)
    offset += typeAndClass.length

    // TTL, in seconds
    response.writeUInt32BE(600, offset)
    offset += 4

    // Length of IP
    response.writeUInt16BE(4, offset)
    offset += 2
    //选择110.242.68.3 如果访问bilibili跳转到baidu
    '127.0.0.1'.split('.').forEach(value => {
        response.writeUInt8(parseInt(value), offset)
        offset += 1
    })
    console.log("aa"+"===="+rinfo.port)
    server.send(response, rinfo.port, rinfo.address, (err) => {
        if (err) {
            console.log(err)
            server.close()
        }
    })
}

function forward(msg, rinfo) {
    const client = dgram.createSocket('udp4')
    client.on('error', (err) => {
        console.log(`client error:\n${err.stack}`)
        client.close()
    })
    client.on('message', (fbMsg, fbRinfo) => {
        server.send(fbMsg, rinfo.port, rinfo.address, (err) => {
            err && console.log(err)
        })
        client.close()
    }) 
    console.log("使用8.8.8.8 dns解析")
    client.send(msg, 53, '8.8.8.8', (err) => {
        if (err) {
            console.log(err)
            client.close()
        }
    })
}

server.on('message', (msg, rinfo) => {
    const host = parseHost(msg.subarray(12))
    
    console.log(rinfo.address+"==="+rinfo.port)
    dns.lookup(host, {all:true},function(err, addresss, family){
        if(err) throw err;
        for(let as of addresss){ 
            console.log(as)
        }
    }); 
    if(/www.bilibili.com/.test(host)) {
        resolve(msg, rinfo) 
    } else {
        forward(msg, rinfo)
    }  
});

server.on('error', (err) => {
    console.log(`server error:\n${err.stack}`)
    server.close()
})

/* server.on('listening', () => {
    const address = server.address()
    console.log(`server listening ${address.address}:${address.port}`)
}) */

server.bind(53)
